% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % 
% matlab有关BP网络的模块：
% 1.   mapminmax函数:用于归一化或反归一化数据
%     (1) [Y,PS] = mapminmax(X)
%         X：原矩阵
%         Y：对矩阵X进行规范化得到的矩阵
%         PS：存放关于原矩阵规范化过程中的相关映射数据的结构体
%     (2) [Y,PS] = mapminmax(X,FP)
%         X：原矩阵
%         FP：含有字段FP.ymin和FP.ymax的结构体
%         Y：对矩阵X进行规范化得到的矩阵（使用在FP的ymin和ymax规定下的算法）
%         PS：存放关于原矩阵规范化过程中的相关映射数据的结构体
%     (3) Y = mapminmax(‘apply’,X,PS)
%         ’apply’：必写
%         X：原矩阵
%         PS：存放关于某个矩阵规范化过程中的相关映射数据的结构体
%         Y：对矩阵X进行规范化得到的矩阵（使用PS中的规范化方式）
%     (4) X = mapminmax(‘reverse’,Y,PS)
%         ’reverse’：必写
%         Y：某个矩阵
%         PS：存放关于某个矩阵规范化过程中的相关映射数据的结构体
%         X：将矩阵Y反规范化得到的矩阵（使用PS中的规范化方式，这里指将矩阵X转换为矩阵Y的规范化方式）
% 2.   newff函数(新版本):建立一个前馈反向传播（BP）网络
%     (1) net=newff（P,T,S）
%         P: 输入数据矩阵。(RxQ1)，其中Q1代表R元的输入向量。其数据意义是矩阵P有Q1列，每一列都是一个样本，而每个样本有R个属性（特征）。一般矩阵P需要事先归一化好，即P的每一行都归一化到[0 1]或者[-1 1]。
%         T：目标数据矩阵。(SNxQ2)，其中Q2代表SN元的目标向量。数据意义参考上面，矩阵T也是事先归一化好的。
%         S：第i层的神经元个数。（新版本中可以省略输出层的神经元个数不写，因为输出层的神经元个数已经取决于T）
%     (2) net = newff(P,T,S,TF,BTF,BLF,PF,IPF,OPF,DDF)（提供了可选择的参数）
%         TF：相关层的传递函数，默认隐含层使用tansig函数，输出层使用purelin函数。
%         BTF：BP神经网络学习训练函数，默认值为trainlm函数。
%         BLF：权重学习函数，默认值为learngdm。
%         PF：性能函数，默认值为mse。
%         PF，OPF，DDF均为默认值即可。
%     (3) 常用的传递函数:
%         purelin：线性传递函数
%         tansig：正切 S 型传递函数
%         logsig： 对数 S 型传递函数
%         (注意：隐含层和输出层函数的选择对BP神经网络预测精度有较大影响，一般隐含层节点传递函数选用tansig函数或logsig函数，输出层节点转移函数选用tansig函数或purelin函数。）
% 3.   train函数:训练一个神经网络
%     (1) [NET2,TR] = train(NET1,X,T)（也可[NET2] = train(NET1,X,T) ）
%         NET1：待训练的网络
%         X: 输入数据矩阵（已归一化）
%         T：目标数据矩阵（已归一化）
%         NET2：训练得到的网络TR:存放有关训练过程的数据的结构体
% 4.   sim函数:模拟Simulink模型,进行数据仿真
%     (1) SimOut = sim(‘MODEL’, PARAMETERS)
%         （见名知意，不必再解释）
% 5.   关于net.trainParam的常用属性：（假定已经定义了一个BP网络net） 
%     (1)* net.trainParam.show: 两次显示之间的训练次数 
%     (2)* net.trainParam.epochs: 最大训练次数 
%     (3)* net.trainParam.lr: 网络的学习速率 
%     (4)* net.trainParam.goal: 训练网络所要达到的目标误差 
%     (5)* net.trainParam.time: 最长训练时间（秒）
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% matlab实现BP网络步骤(以"BP神经网络.docx"里的公路运输为例)：
% BP网络创建：
% 1.准备好训练集（以矩阵的方式存储）
%   输入层数据：p = [numberOfPeople; numberOfAutomobile; roadArea];
%   输出数据：t = [passengerVolume; freightVolume];
% 2.对训练集中的输入数据矩阵和目标数据矩阵进行归一化处理
%   [pn, inputStr] = mapminmax(p);
%   [tn, outputStr] = mapminmax(t);
% 3.建立BP神经网络
%   net = newff(pn, tn, [3 7 2], {'purelin', 'logsig', 'purelin'});
%   [3 7 2]:3为输入层的节点个数，7为隐含层的“神经元”节点个数（可由l =
%   sqrt(n+m)+a得出，具体可看“BP神经网络.docx”），2为输出层的节点个数
% 4.神经网络参数设置
%   net.trainParam.show = 10;%每10轮回显示一次结果
%   net.trainParam.epochs = 5000;%最大训练次数
%   net.trainParam.lr = 0.05;%网络的学习速率
%   net.trainParam.goal = 0.65 * 10^(-3);%训练网络所要达到的目标误差
%   net.divideFcn = '';%网络误差如果连续6次迭代都没变化，则matlab会默认终止训练。为了让程序继续运行，用以下命令取消这条设置
% 5.开始训练网络
%   net = train(net, pn, tn);
% 到此BP网络训练完成！！！！！
% 
% 
% 使用BP网络进行预测：
% 1.新输入要用于预测的数据
%   newInput = [73.39 75.55; 3.9635 4.0975; 0.9880 1.0268]; 
%2.利用原始输入数据(训练集的输入数据)的归一化参数对新输入数据进行归一化
%  newInput = mapminmax('apply', newInput, inputStr);
%3.进行仿真
%  newOutput = sim(net, newInput);
%4.反归一化得到结果
%  newOutput = mapminmax('reverse',newOutput, outputStr);
% newOutput为预测的结果，以矩阵的方式存储
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %

clc
clear
%准备好训练集
%人数(单位：万人)
numberOfPeople=[20.55 22.44 25.37 27.13 29.45 30.10 30.96 34.06 36.42 38.09 39.13 39.99 41.93 44.59 47.30 52.89 55.73 56.76 59.17 60.63];
%机动车数(单位：万辆)
numberOfAutomobile=[0.6 0.75 0.85 0.9 1.05 1.35 1.45 1.6 1.7 1.85 2.15 2.2 2.25 2.35 2.5 2.6 2.7 2.85 2.95 3.1];
%公路面积(单位：万平方公里)
roadArea=[0.09 0.11 0.11 0.14 0.20 0.23 0.23 0.32 0.32 0.34 0.36 0.36 0.38 0.49 0.56 0.59 0.59 0.67 0.69 0.79];
%公路客运量(单位：万人)
passengerVolume = [5126 6217 7730 9145 10460 11387 12353 15750 18304 19836 21024 19490 20433 22598 25107 33442 36836 40548 42927 43462];
%公路货运量(单位：万吨)
freightVolume = [1237 1379 1385 1399 1663 1714 1834 4322 8132 8936 11099 11203 10524 11115 13320 16762 18673 20724 20803 21804];

%输入数据矩阵
p = [numberOfPeople; numberOfAutomobile; roadArea];%%三个输入层
%目标（输出）数据矩阵
t = [passengerVolume; freightVolume];%%两个输出层

%对训练集中的输入数据矩阵和目标数据矩阵进行归一化处理
[pn, inputStr] = mapminmax(p);
[tn, outputStr] = mapminmax(t);

%建立BP神经网络
net = newff(pn, tn, [3 7 2], {'purelin', 'logsig', 'purelin'});

%每10轮回显示一次结果
net.trainParam.show = 10;

%最大训练次数
net.trainParam.epochs = 5000;

%网络的学习速率
net.trainParam.lr = 0.05;

%训练网络所要达到的目标误差
net.trainParam.goal = 0.65 * 10^(-3);

%网络误差如果连续6次迭代都没变化，则matlab会默认终止训练。为了让程序继续运行，用以下命令取消这条设置
net.divideFcn = '';

%开始训练网络
net = train(net, pn, tn);

%使用训练好的网络，基于训练集的数据对BP网络进行仿真得到网络输出结果
%(因为输入样本（训练集）容量较少，否则一般必须用新鲜数据进行仿真测试)
answer = sim(net, pn);
% 
% %反归一化
answer1 = mapminmax('reverse', answer, outputStr);


%-----------------绘制测试样本神经网络输出和实际样本输出的对比图(figure(1))--------------------
t = 1990:2009;

%测试样本网络输出客运量
a1 = answer1(1,:); 
%测试样本网络输出货运量
a2 = answer1(2,:);

figure(1);
subplot(2, 1, 1); 
plot(t, a1, 'ro', t, passengerVolume, 'b+');
legend('网络输出客运量', '实际客运量');
xlabel('年份'); ylabel('客运量/万人');
title('神经网络客运量学习与测试对比图');
grid on;

subplot(2, 1, 2); plot(t, a2, 'ro', t, freightVolume, 'b+');
legend('网络输出货运量', '实际货运量');
xlabel('年份'); ylabel('货运量/万吨');
title('神经网络货运量学习与测试对比图');
grid on;
%-----------------绘制测试样本神经网络输出和实际样本输出测试结束--------------------







%-----------------开始新输入数据进行预测的对比图(figure(2))--------------------
%使用训练好的神经网络对新输入数据进行预测
%新输入数据(2010年和2011年的相关数据)
newInput = [73.39 75.55; 3.9635 4.0975; 0.9880 1.0268]; 

%利用原始输入数据(训练集的输入数据)的归一化参数对新输入数据进行归一化
newInput = mapminmax('apply', newInput, inputStr);

%进行仿真
newOutput = sim(net, newInput);

%反归一化
newOutput = mapminmax('reverse',newOutput, outputStr);

disp('预测2010和2011年的公路客运量分别为(单位：万人)：');
newOutput(1,:)
disp('预测2010和2011年的公路货运量分别为(单位：万吨)：');
newOutput(2,:)

%在figure(1)的基础上绘制2010和2011年的预测情况-------------------------------------------------------
figure(2);
t1 = 1990:2011;

subplot(2, 1, 1); 
plot(t1, [a1 newOutput(1,:)], 'ro', t, passengerVolume, 'b+');
legend('网络输出客运量', '实际客运量');
xlabel('年份'); ylabel('客运量/万人');
title('神经网络客运量学习与测试对比图(添加了预测数据)');
grid on;

subplot(2, 1, 2); plot(t1, [a2 newOutput(2,:)], 'ro', t, freightVolume, 'b+');
legend('网络输出货运量', '实际货运量');
xlabel('年份'); ylabel('货运量/万吨');
title('神经网络货运量学习与测试对比图(添加了预测数据)');
grid on;



